﻿using System;
using Silver3D.Math;

namespace Silver3D.Graphics
{
    public class SkewTransform : MatrixTransform
    {
        private Vec3 rotateAxis = Vec3.XAxis;
        private Vec3 aroundAxis = Vec3.YAxis;
        private double angle = 0.0;

        public Vec3 RotateAxis
        {
            get { return rotateAxis; }
            set
            {
                rotateAxis = value;
                IsDirty = true;
            }
        }

        public Vec3 AroundAxis
        {
            get { return aroundAxis; }
            set
            {
                aroundAxis = value;
                IsDirty = true;
            }
        }

        public double Angle
        {
            get { return angle; }
            set
            {
                angle = value;
                IsDirty = true;
            }
        }

        public double AngleDegrees
        {
            get { return Angle * Util.RadToDeg; }
            set { Angle = value * Util.DegToRad; }
        }

        public SkewTransform(Scene scene, string id)
            : base(scene, id)
        {
        }

        public SkewTransform(Scene scene, string id, Node parent)
            : base(scene, id, parent)
        {
        }

        public SkewTransform(Scene scene, string id, Node parent, Vec3 rotateAxis, Vec3 aroundAxis, double angleInDegrees)
            : base(scene, id, parent)
        {
            RotateAxis = rotateAxis;
            AroundAxis = aroundAxis;
            AngleDegrees = angleInDegrees;
        }

        protected override void UpdateMatrix()
        {
            double s = System.Math.Tan(angle);

            CachedMatrix = new Matrix44(
                1.0 + s * rotateAxis.X * aroundAxis.X, s * rotateAxis.Y * aroundAxis.X, s * rotateAxis.Z * aroundAxis.X, 0.0,
                s * rotateAxis.X * aroundAxis.Y, 1.0 + s * rotateAxis.Y * aroundAxis.Y, s * rotateAxis.Z * aroundAxis.Y, 0.0,
                s * rotateAxis.X * aroundAxis.Z, s * rotateAxis.Y * aroundAxis.Z, 1.0 + s * rotateAxis.Z * aroundAxis.Z, 0.0,
                0.0, 0.0, 0.0, 1.0);
        }
    }
}
